﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace RoadSystemTest
{
    /// <summary>
    /// Interaction logic for CrossRoad.xaml
    /// </summary>
    public partial class CrossRoad : UserControl, ITrafficObject
    {
        private Point Position { get; set; }
        public Point GetPosition() { return Position; }
        public void SetPosition(Point pos) { Position = pos; RefreshPosition(); }

        //A lámpák aktuális állása
        private bool VerticalLight { get; set; }
        private bool HorizontalLight { get; set; }

        private bool LanePointsVisible { get; set; }
        public void SetLanePointsVisible(bool visible) { LanePointsVisible = visible; UpdateLanePoints(); }
        public bool IsLanePointsVisible() { return LanePointsVisible; }

        private bool Selected { get; set; }

        public int lightInterval { get; set; }

        public void SetInterval(int i)
        {
            lightInterval = i;
            lights.Stop();
            lights2.Stop();
            lights.Interval = new TimeSpan(0, 0, lightInterval);
            lights.Start();
        }

        DispatcherTimer lights;
        DispatcherTimer lights2;

        public CrossRoad(Point p, int l = 2)
        {
            InitializeComponent();
            Position = new Point(p);
            Selected = false;
            lightInterval = l;
                                
            HorizontalForwardLane = new Lane(this, Sites.Horizontal, LaneTypes.Forward);
            HorizontalBackwardLane = new Lane(this, Sites.Horizontal, LaneTypes.Backward);
            VerticalForwardLane = new Lane(this, Sites.Vertical, LaneTypes.Forward);
            VerticalBackwardLane = new Lane(this, Sites.Vertical, LaneTypes.Backward);

            SetPosition(p);

            HorizontalLight = false;
            VerticalLight = true;
            HorizontalForwardLane.SetCanEnter(false);
            HorizontalBackwardLane.SetCanEnter(false);
            VerticalForwardLane.SetCanEnter(false);
            VerticalBackwardLane.SetCanEnter(false);


            lights2 = new DispatcherTimer();
            lights2.Interval = new TimeSpan(0, 0, 3);
            lights2.Tick += timer_Tick;
            lights2.Tag = true;
            lights = new DispatcherTimer();
            lights.Interval = new TimeSpan(0, 0, lightInterval);
            lights.Tick += lights_Tick;
            lights.Tag = false;
            RefreshLights();

            SetLanePointsVisible(false);            
        }

        private void RefreshPosition()
        {
            ((TranslateTransform)this.RenderTransform).X = Position.X;
            ((TranslateTransform)this.RenderTransform).Y = Position.Y;

            double xHorizontalDelta = 50 + 40;
            double yHorizontalDelta = 50 - 20;
            double xVerticalDelta = 50 - 20;
            double yVerticalDelta = 50 + 40;
            double margin = 10;
            double translate = 50;

            Point hfsPos = new Point { X = -xHorizontalDelta - margin + translate, Y = yHorizontalDelta + translate };
            Point hfePos = new Point { X = xHorizontalDelta + margin + translate, Y = yHorizontalDelta + translate };
            Point hbsPos = new Point { X = xHorizontalDelta + margin + translate, Y = -yHorizontalDelta + translate };
            Point hbePos = new Point { X = -xHorizontalDelta - margin + translate, Y = -yHorizontalDelta + translate };
            Point vfsPos = new Point { X = xVerticalDelta + translate, Y = yVerticalDelta + margin + translate };
            Point vfePos = new Point { X = xVerticalDelta + translate, Y = -yVerticalDelta - margin + translate };
            Point vbsPos = new Point { X = -xVerticalDelta + translate, Y = -yVerticalDelta - margin + translate };
            Point vbePos = new Point { X = -xVerticalDelta + translate, Y = yVerticalDelta + margin + translate };

            hfsPos.ApplyToTranslateTransform(HorizontalForwardStart);
            hfePos.ApplyToTranslateTransform(HorizontalForwardEnd);
            hbsPos.ApplyToTranslateTransform(HorizontalBackwardStart);
            hbePos.ApplyToTranslateTransform(HorizontalBackwardEnd);
            vfsPos.ApplyToTranslateTransform(VerticalForwardStart);
            vfePos.ApplyToTranslateTransform(VerticalForwardEnd);
            vbsPos.ApplyToTranslateTransform(VerticalBackwardStart);
            vbePos.ApplyToTranslateTransform(VerticalBackwardEnd);

            HorizontalForwardLane.StartPosition = hfsPos;
            HorizontalForwardLane.EndPosition = hfePos;
            HorizontalBackwardLane.StartPosition = hbsPos;
            HorizontalBackwardLane.EndPosition = hbePos;
            VerticalForwardLane.StartPosition = vfsPos;
            VerticalForwardLane.EndPosition = vfePos;
            VerticalBackwardLane.StartPosition = vbsPos;
            VerticalBackwardLane.EndPosition = vbePos;
        }

        private void UpdateLanePoints()
        {
            HorizontalForwardStartRect.Visibility = LanePointsVisible ? Visibility.Visible : Visibility.Hidden;
            HorizontalForwardEndRect.Visibility = LanePointsVisible ? Visibility.Visible : Visibility.Hidden;
            HorizontalBackwardStartRect.Visibility = LanePointsVisible ? Visibility.Visible : Visibility.Hidden;
            HorizontalBackwardEndRect.Visibility = LanePointsVisible ? Visibility.Visible : Visibility.Hidden;
            VerticalForwardStartRect.Visibility = LanePointsVisible ? Visibility.Visible : Visibility.Hidden;
            VerticalForwardEndRect.Visibility = LanePointsVisible ? Visibility.Visible : Visibility.Hidden;
            VerticalBackwardStartRect.Visibility = LanePointsVisible ? Visibility.Visible : Visibility.Hidden;
            VerticalBackwardEndRect.Visibility = LanePointsVisible ? Visibility.Visible : Visibility.Hidden;
        }

        void RefreshLights(bool allRed = false)
        {
            if (allRed)
            {
                TopLight.Fill = Brushes.Red;
                BottomLight.Fill = Brushes.Red;
                RightLight.Fill = Brushes.Red;
                LeftLight.Fill = Brushes.Red;
                return;
            }

            if (VerticalLight)
            {
                TopLight.Fill = Brushes.Green;
                BottomLight.Fill = Brushes.Green;
            }
            else
            {
                TopLight.Fill = Brushes.Red;
                BottomLight.Fill = Brushes.Red;
            }
            if (HorizontalLight)
            {
                RightLight.Fill = Brushes.Green;
                LeftLight.Fill = Brushes.Green;
            }
            else
            {
                RightLight.Fill = Brushes.Red;
                LeftLight.Fill = Brushes.Red;
            }
        }

        //Lámpa váltás. Először az összeset pirosra állítja, majd egy idő után vált
        void lights_Tick(object sender, EventArgs e)
        {
            VerticalForwardLane.SetCanEnter(false);
            VerticalBackwardLane.SetCanEnter(false);
            HorizontalForwardLane.SetCanEnter(false);
            HorizontalBackwardLane.SetCanEnter(false);
            VerticalLight = !VerticalLight;
            HorizontalLight = !HorizontalLight;
            RefreshLights(true);
            
            lights.Stop();
            lights2.Start();
        }

        //A konkrét váltás a lámpáknál
        void timer_Tick(object sender, EventArgs e)
        {
            lights2.Stop();
            lights.Start();
            RefreshLights();
            VerticalForwardLane.SetCanEnter(VerticalLight);
            VerticalBackwardLane.SetCanEnter(VerticalLight);
            HorizontalForwardLane.SetCanEnter(HorizontalLight);
            HorizontalBackwardLane.SetCanEnter(HorizontalLight);
            
            
        }

        public void StopLights()
        {
            if (IsLightsStopped())
            {
                return;
            }
            if (lights2.IsEnabled)
            {
                lights2.Stop();
                lights.Stop();
                lights2.Tag = true;
                lights.Tag = false;
            }
            else
            {
                lights.Stop();
                lights2.Stop();
                lights2.Tag = false;
                lights.Tag = true;
            }
        }

        public void StartLights()
        {
            if (!IsLightsStopped())
            {
                return;
            }
            if ((bool)lights2.Tag == true)
            {
                lights2.Start();
            }
            else
            {
                lights.Start();
            }
        }

        public bool IsLightsStopped()
        {
            return !lights2.IsEnabled && !lights.IsEnabled;
        }

        public void Reset()
        {
            HorizontalForwardLane.RemoveAllCars();
            HorizontalBackwardLane.RemoveAllCars();
            VerticalForwardLane.RemoveAllCars();
            VerticalBackwardLane.RemoveAllCars();
        }

        public void Select()
        {
            if (Selected)
            {
                return;
            }
            Selected = true;
            
            RefreshBackground();
        }
        public void Deselect()
        {
            if (!Selected)
            {
                return;
            }
            Selected = false;
            RefreshBackground();
        }

        public bool IsSelected()
        {
            return Selected;
        }

        private void RefreshBackground()
        {
            if (Selected)
            {
                BackgroundRect.Fill = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FF2D799C"));
            }
            else
            {
                BackgroundRect.Fill = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FF686868"));
            }
        }

        public Lane HorizontalForwardLane { get; private set; }
        public Lane HorizontalBackwardLane { get; private set; }
        public Lane VerticalForwardLane { get; private set; }
        public Lane VerticalBackwardLane { get; private set; }
        public Road NorthRoad { get; private set; }
        public Road SouthRoad { get; private set; }
        public Road EastRoad { get; private set; }
        public Road WestRoad { get; private set; }

        public void ConnectEastRoad(Road r)
        {
            if (EastRoad != null)
            {
                EastRoad.BackwardLane.Connect(null);
            }
            EastRoad = r;
            if (EastRoad != null)
            {
                EastRoad.BackwardLane.Connect(HorizontalBackwardLane);
                HorizontalForwardLane.Connect(EastRoad.ForwardLane);
            }
            else
            {
                HorizontalForwardLane.Connect(null);
            }
        }

        public void ConnectWestRoad(Road r)
        {
            if (WestRoad != null)
            {
                WestRoad.ForwardLane.Connect(null);
            }
            WestRoad = r;
            if (WestRoad != null)
            {
                WestRoad.ForwardLane.Connect(HorizontalForwardLane);
                HorizontalBackwardLane.Connect(WestRoad.BackwardLane);
            }
            else
            {
                HorizontalBackwardLane.Connect(null);
            }
        }

        public void ConnectNorthRoad(Road r)
        {
            if (NorthRoad != null)
            {
                NorthRoad.BackwardLane.Connect(null);
            }
            NorthRoad = r;
            if (NorthRoad != null)
            {
                NorthRoad.BackwardLane.Connect(VerticalBackwardLane);
                VerticalForwardLane.Connect(NorthRoad.ForwardLane);
            }
            else
            {
                VerticalForwardLane.Connect(null);
            }
            
        }

        public void ConnectSouthRoad(Road r)
        {
            if (SouthRoad != null)
            {
                SouthRoad.ForwardLane.Connect(null);
            }
            SouthRoad = r;
            if (SouthRoad != null)
            {
                SouthRoad.ForwardLane.Connect(VerticalForwardLane);
                VerticalBackwardLane.Connect(SouthRoad.BackwardLane);
            }
            else
            {
                VerticalBackwardLane.Connect(null);
            }
            
        }

        public void DisconnectNorthRoad()
        {
            VerticalForwardLane.Disconnect();
            NorthRoad.BackwardLane.Disconnect();
            NorthRoad = null;
        }

        public void DisconnectSouthRoad()
        {
            VerticalBackwardLane.Disconnect();
            SouthRoad.ForwardLane.Disconnect();
            SouthRoad = null;
        }

        public void DisconnectEastRoad()
        {
            HorizontalForwardLane.Disconnect();
            EastRoad.BackwardLane.Disconnect();
            EastRoad = null;
        }

        public void DisconnectWestRoad()
        {
            HorizontalBackwardLane.Disconnect();
            WestRoad.ForwardLane.Disconnect();
            WestRoad = null;
        }

        private void HorizontalForwardLane_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            LaneClick(HorizontalForwardLane, new Point(HorizontalForwardStart.X, HorizontalForwardStart.Y),
                new Point(HorizontalForwardEnd.X, HorizontalForwardEnd.Y));
        }

        private void HorizontalBackwardLane_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            LaneClick(HorizontalBackwardLane, new Point(HorizontalBackwardStart.X, HorizontalBackwardStart.Y),
                new Point(HorizontalBackwardEnd.X, HorizontalBackwardEnd.Y));
        }

        private void VerticalBackwardLane_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            LaneClick(VerticalBackwardLane, new Point(VerticalBackwardStart.X, VerticalBackwardStart.Y),
                new Point(VerticalBackwardEnd.X, VerticalBackwardEnd.Y));
        }

        private void VerticalForwardLane_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            LaneClick(VerticalForwardLane, new Point(VerticalForwardStart.X, VerticalForwardStart.Y),
                new Point(VerticalForwardEnd.X, VerticalForwardEnd.Y));
        }
        public event TrafficEventHandler OnLaneClick;
        private void LaneClick(ILaneObject lane, Point start, Point end)
        {
            if (OnLaneClick != null)
                OnLaneClick(this, new TrafficEventArgs { lane = lane, laneStart = start, laneEnd = end });
        }
    }
}
